<html>
    <head>
        <title>取消后台作业</title>
    </head>
    <body>
        <script>
            /*
                        四、取消后台工作

                                如果你的后台作业是可取消的，那么你可以使用标准的"取消令牌系统" 来获取 CancellationToken， 以在请求是取消你的后台作业。

                                请参考一下使用 ICancellationTokenProvider 获取取消令牌的示例：

                                        using System;
                                        using System.Threading.Tasks;
                                        using Microsoft.Extensions.Logging;
                                        using Volo.Abp.DependencyInjection;
                                        using Volo.Abp.Threading;

                                        namespace MyProject
                                        {
                                            // 后台作业类：实现 ITransientDependency 接口
                                            public class LongRunningJob : AsyncBackgroundJob<LongRunningJobArgs>, ITransientDependency
                                            {
                                                private readonly ICancellationTokenProvider _cancellationTokenProvider;

                                                public LongRunningJob(ICancellationTokenProvider cancellationTokenProvider)
                                                {
                                                    _cancellationTokenProvider = cancellationTokenProvider; 
                                                    // 注入 ICancellationTokenProvider 该服务用于获取当前任务的取消令牌
                                                }

                                                // 异步执行当前后台作业
                                                public override async Task ExecuteAsync(LongRunningJobArgs args)
                                                {
                                                    foreach (var id in args.Ids)
                                                    {
                                                        // 每次迭代前通过 ThrowIfCancellationRequested() 检查是否被取消
                                                        // 若收到取消请求，立即抛出 OperationCanceledException 终止作业
                                                        _cancellationTokenProvider.Token.ThrowIfCancellationRequested();
                                                        
                                                        await ProcessAsync(id); // 根据任务ID 处理任务
                                                    }
                                                }
                                            }
                                        } 
                                            
                                   关键设计特点：
                                   
                                          1、 可取消性设计：

                                                通过标准CancellationToken实现协作式取消
                                                确保长时间任务能被及时中断
                                                
                                          2、任务分段处理：
                                         
                                                将大任务拆分为多个小单元（按id处理）
                                                每个单元处理前检查取消状态，避免处理到一半被终止
                                                
                                           3、ABP后台作业特性：

                                                自动重试机制（默认重试3次）
                                                持久化存储（作业状态在重启后依然保留）
                                                分布式支持（适用于集群环境）
                                                
                                    如果应用程序正在关闭，并且我们不想在后台作业中阻止应用程序关闭，则可能需要取消后台作业。
                                    如果请求取消，此例会引发异常。因此，下次应用程序启动时将重试该作业。
                                    如果你不想这么做，只需要从ExecuteAsync方法返回而不会引发任何异常。
                                    （你可以简单地检查_cancellationTokenProvider.Token.IsCancellationRequested属性）
                                    
                    */
        </script>
    </body>
</html>